package com.imu.core.redis;
	 
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.imu.utils.EncryptUtil;
import redis.clients.jedis.JedisPoolConfig;
 
/**
 * redis 缓存配置;
 * 注意：RedisCacheConfig这里也可以不用继承：CachingConfigurerSupport，也就是直接一个普通的Class就好了；
 * 这里主要我们之后要重新实现 key的生成策略，只要这里修改KeyGenerator，其它位置不用修改就生效了。
 * 普通使用普通类的方式的话，那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。
 * @version v.0.1
 */
@Configuration
@EnableCaching//启用缓存，这个注解很重要；
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfiguration extends CachingConfigurerSupport
{
	@Bean(destroyMethod = "destroy")
    public JedisConnectionFactory redisConnectionFactory()
	{
		// redis 连接池配置
		JedisPoolConfig poolConfig = new JedisPoolConfig();
		poolConfig.setMaxIdle(properties.getMaxIdle());
		poolConfig.setMaxTotal(properties.getMaxTotal());
		poolConfig.setMinIdle(properties.getMinIdle());
		poolConfig.setMaxWaitMillis(properties.getMaxWaitMillis());
		poolConfig.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis());
		poolConfig.setNumTestsPerEvictionRun(properties.getNumTestsPerEvictionRun());
		poolConfig.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis());
		poolConfig.setTestOnBorrow(properties.isTestOnBorrow());
		poolConfig.setTestOnReturn(properties.isTestOnReturn());
		poolConfig.setTestWhileIdle(properties.isTestWhileIdle());
		
		String password = "";//解密
		try {
			password = EncryptUtil.decrypt(properties.getPassword());
		}
		catch (Exception e){}
		
        // redis 连接工厂
		JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();  
        redisConnectionFactory.setPoolConfig(poolConfig);
        redisConnectionFactory.setHostName(properties.getHost());  
        redisConnectionFactory.setPort(properties.getPort());
        if(StringUtils.isNotEmpty(properties.getPassword())){
            redisConnectionFactory.setPassword(password);
        }
        redisConnectionFactory.setDatabase(properties.getDatabase());
        redisConnectionFactory.setTimeout(properties.getTimeout());
        redisConnectionFactory.setUsePool(properties.isUsePool());
        logger.info(">>>>>>>>>>>>>>>JedisConnectionFactory init success<<<<<<<<<<<<<");
        return redisConnectionFactory;  
    }  
	
    /**
     * redis模板操作类,类似于jdbcTemplate的一个类;
     * 虽然CacheManager也能获取到Cache对象，但是操作起来没有那么灵活；
     * 这里在扩展下：RedisTemplate这个类不见得很好操作，我们可以在进行扩展一个我们
     * 自己的缓存类，比如：RedisStorage类;
     * @param factory : 通过Spring进行注入，参数在application.properties进行配置；
     * @return
     */
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory)
    {
       RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
       redisTemplate.setConnectionFactory(factory);
      
       //key序列化方式;（不然会出现乱码;）,但是如果方法上有Long等非String类型的话，会报类型转换错误；
       //所以在没有自己定义key生成策略的时候，以下这个代码建议不要这么写，可以不配置或者自己实现ObjectRedisSerializer
       //或者JdkSerializationRedisSerializer序列化方式;
       //RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
       redisTemplate.setKeySerializer(new StringRedisSerializer());
       redisTemplate.setHashKeySerializer(new StringRedisSerializer());
       redisTemplate.setValueSerializer(new StringRedisSerializer());
       redisTemplate.setHashValueSerializer(new StringRedisSerializer());
       //redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
       //redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

       logger.info(">>>>>>>>>>>>>>>RedisTemplate init success<<<<<<<<<<<<<");
       return redisTemplate;
    }
    
    @Autowired
    private RedisProperties properties;
    private static final Logger logger = LoggerFactory.getLogger(RedisAutoConfiguration.class);
}
